﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using StedySoft.SenseSDK;
using Interfaces;
using Map;

namespace Porter
{
    public partial class CtlStationList : UserControl
    {
        private int _childLevel = -1;
        private string currentFilter;
        private List<string> currentList = new List<string>();
        private List<long> currentMarkerIds = new List<long>();
        private List<Service.StationLine> currentFilterResult;
        private List<string> keywords = new List<string>() { "bus", "metro" };

        public CtlStationList()
        {
            InitializeComponent();
            currentFilter = Global.Settings.Get("DefaultFilter") as string;
            currentFilterResult = new List<Service.StationLine>();
            this.listStops = new SenseListControl()
            {
                Dock = System.Windows.Forms.DockStyle.Fill,
                FocusedItem = null,
                IsSecondaryScrollType = false,
                MinimumMovement = 15,
                Name = "listStations",
                ShowScrollIndicator = true,
                Height = this.Height,
                Springback = 0.35F,
                TabIndex = 1,
                ThreadSleep = 100,
                TopIndex = 0,
                Velocity = 0.9F
            };
            listStops.OnBeforeShowItemChildren += new SenseListControl.BeforeShowItemChildrenHandler(listStops_OnBeforeShowItemChildren);
            listStops.OnShowItemChildren += new SenseListControl.ShowItemChildrenHandler(listStops_OnShowItemChildren);
            listStops.OnHideItemChildren += new SenseListControl.HideItemChildrenHandler(listStops_OnHideItemChildren);

            SensePanelTextboxItem itmSearchBox = new SensePanelTextboxItem()
            {
                Name = "Filter",
                LabelText = "Filter",
                Text = currentFilter
            };
            itmSearchBox.TextChanged += delegate(object Sender, EventArgs e)
            {
                if (this.FilterChanged(itmSearchBox.Text))
                {
                    currentFilter = itmSearchBox.Text;
                    this.Clear();
                    this.Populate();
                }
            };
            this.listStops.AddItem(itmSearchBox);
            this.Controls.Add(this.listStops);
            if(this.RefreshData()) this.Populate();
        }

        public bool RefreshData()
        {
            if (Double.IsNaN(Global.m_middleware.LastFixPosition.Latitude) || Double.IsNaN(Global.m_middleware.LastFixPosition.Longitude))
            {
                // TODO: lecserélni menüitemre, és egy textboxra, ahol kézzel megadható a pozíció
                MessageBox.Show("No position data available!");
                return false;
            }
            else
            {
                Global.m_service.Request(Service.Function.StationLines, new Service.Parameters()
                {
                    stLat = Global.m_middleware.LastFixPosition.Latitude,
                    stLng = Global.m_middleware.LastFixPosition.Longitude,
                    dist = (int)Global.Settings.Get("DefaultDistance")
                });
                if (Global.m_service.ResponseCache[Service.Function.StationLines].Response.code == -7)
                {
                    // TODO: lecserélni menüitemekre
                    MessageBox.Show("Sorry, there is no public transport in the specified area! Try to increase the search radius!");
                    return false;
                }
                if (Global.m_service.ResponseCache[Service.Function.StationLines].Response.code <= 0)
                    return false;
            }
            return true;
        }

        private void Filter(string filter)
        {
            currentFilterResult.Clear();
            foreach (Service.StationLine station in
                     Global.m_service.ResponseCache[Service.Function.StationLines].Response.StationLines.StationLine)
            { // TODO: implement the actual filters
                switch (station.ltId)
                {
                    case (int)VehicleType.LocalBus:
                        if (currentFilter.Contains("-bus")) continue;
                        break;
                    case (int)VehicleType.Metro:
                        if (currentFilter.Contains("-metro")) continue;
                        break;
                }
                currentFilterResult.Add(station);
            }
        }

        public void Populate()
        {
            try
            {
                /* Showing the list of stations and placing markers on the map */

                listStops.BeginUpdate();

                this.Filter(currentFilter);
                listStops.AddItem(new SensePanelDividerItem("lbInfo", String.Format("{0} stop(s) in {1} meters",
                                                            currentFilterResult.Count,
                                                            (int)Global.Settings.Get("DefaultDistance") * 1000)));

                foreach (Service.StationLine station in currentFilterResult)
                {
                    double dist = GPSData.CalculateDistance(Global.m_middleware.LastFixPosition, station.stLat, station.stLng);
                    SensePanelMoreItem item = new SensePanelMoreItem()
                    {
                        Name = String.Format("{0}:{1}:{2}:{3}", station.lnId, station.stId, station.EndStations.stId, station.lnNumber),
                        PrimaryText = dist > 1 ? String.Format("{0:0.0} km - {1}", dist, station.stName) :
                                                 String.Format("{0:0} m - {1}", dist / 1000, station.stName),
                        SecondaryText = String.Format("[{0}] to {1}", station.lnNumber, station.EndStations.stName),
                        Enabled = true,
                        ProcessEntireButton = false
                    };
                    this.currentList.Add(String.Format("{0}:{1}:{2}:{3}", station.lnId, station.stId, station.EndStations.stId, station.lnNumber));
                    item.OnClick += new SensePanelMoreItem.ClickEventHandler(item_OnClick);
                    item.Thumbnail = new Bitmap(Porter.Graphics.Vehicle.Icon.GetStream((VehicleType)station.ltId));

                    currentMarkerIds.Add(Global.map.AddMarker(station.stLat, station.stLng, Global.VehicleMarkerCache[(VehicleType)station.ltId]));
                    listStops.AddItem(item);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                System.Diagnostics.Debug.WriteLine("Error: " + ex.Message);
            }
            finally
            {
                if (listStops != null) listStops.EndUpdate();
                this.ResumeLayout();
            }
        }

        void listStops_OnBeforeShowItemChildren(SenseListControl.ISenseListItem Sender, ref bool Cancel)
        {
            SensePanelMoreItem itmMore = Sender as SensePanelMoreItem;
            itmMore.Children.Clear();
            Service.Response r = Global.m_service.Request(Service.Function.LineInfo, new Service.Parameters()
            {
                lnId = new List<int>() { int.Parse(itmMore.Name.Split(':')[0]) }
            });
            if (r.code > 0)
            {
                List<DateTime> dT = r.LineInfo.GetDepartures(1); //valamiért null, debuggolni kell belül
                if (dT.Count > 0)
                {
                    string temp = r.LineInfo.GetDepartures(1)[0].ToShortTimeString();
                    itmMore.Children.Add(new SensePanelItem()
                    {
                        PrimaryText = "Next departure",
                        SecondaryText = String.Format("{0}", temp)
                    });
                    foreach (Porter.Service.StationDetail sd in r.LineInfo.Stations)
                    {
                        // TODO: ezt ki kéne találni, hogy hogy... (ez csak teszt!)
                        if (sd.slRoute == 0)
                        {
                            itmMore.Children.Add(new SensePanelItem()
                            {
                                PrimaryText = String.Format("{0,-30}{1}", sd.stName, sd.slTime)
                            });
                        }
                    }
                }
                else
                {
                    MessageBox.Show("Sorry, no timetable available for this route!");
                }
            }
        }

        void listStops_OnShowItemChildren(SenseListControl.ISenseListItem Sender)
        {
            this._childLevel++;
        }

        void listStops_OnHideItemChildren(SenseListControl.ISenseListItem Sender)
        {
            this._childLevel--;
        }

        bool FilterChanged(string newFilter)
        {
            foreach (string keyword in keywords)
            {
                if (newFilter.Contains(keyword) != currentFilter.Contains(keyword))
                {
                    return true;
                }
            }
            return false;
        }

        void Clear()
        {
            this.listStops.BeginUpdate();
            this.listStops.RemoveItem("lbInfo");
            foreach (string item in currentList)
            {
                this.listStops.RemoveItem(item);
            }
            this.currentList.Clear();
            this.listStops.EndUpdate();
            foreach (long id in currentMarkerIds)
                Global.map.RemoveMarker(id);
        }

        void item_OnClick(object Sender)
        {
            if (Global.map.Visible == true)
            {
                SensePanelMoreItem item = (SensePanelMoreItem)Sender;
                foreach (Service.StationLine station in Global.m_service.ResponseCache[Service.Function.StationLines].Response.StationLines.StationLine)
                {
                    string temp = item.PrimaryText.Split('-')[1];
                    if (String.Compare(item.PrimaryText.Split('-')[1].Trim(), station.stName) == 0)
                    {
                        Global.map.Fit(Global.map.MaxZoom, new GeoPoint(station.stLat, station.stLng));
                        return;
                    }
                }
            }
        }
    }
}
